package com.david.config.config;

import com.david.common.utils.SpringContextUtils;
import com.david.config.filter.JwtAuthorizationFilter;
import com.david.config.handler.AuthAccessDeniedHandler;
import com.david.config.handler.AuthEntryPointHandler;
import com.david.system.pojo.Entity.RoleEntity;
import com.david.system.pojo.Entity.UserEntity;
import com.david.system.pojo.VO.MenuWithRoleVO;
import com.david.system.service.SysUserService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.authorization.AuthorizationDecision;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.util.AntPathMatcher;

import java.util.Collection;
import java.util.List;

@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfig {
    private final UserDetailsService userDetailsService;
    private final AuthAccessDeniedHandler accessDeniedHandler;
    private final AuthEntryPointHandler authEntryPointHandler;

    //加载用户信息
    @Bean
    public UserDetailsService userDetailsService() {
        return userDetailsService;
    }
    // 加载密码编码器
    @Bean
    public BCryptPasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
    // 身份验证处理器
    @Bean
    public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
        return authenticationConfiguration.getAuthenticationManager();
    }
    // 处理身份验证
    @Bean
    public AuthenticationProvider authenticationProvider() {
        DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
        daoAuthenticationProvider.setPasswordEncoder(passwordEncoder());
        daoAuthenticationProvider.setUserDetailsService(userDetailsService);
        return  daoAuthenticationProvider;
    }
    @Autowired
    private SysUserService sysUserService;
//    private final SysUserService sysUserService;
    // 配置SecurityFilterChiain过滤器链
    @Bean
    public SecurityFilterChain defaultSecurityFilterChain(HttpSecurity httpSecurity) throws Exception {
        System.out.println("----------------启动过滤器链-----------------------");
        httpSecurity.authorizeHttpRequests(authorizeHttpRequests -> authorizeHttpRequests
                .requestMatchers(HttpMethod.POST, "/auth/login").permitAll()
                .anyRequest().access(
                        (authentication, object) -> {
                    System.out.println("------------动态权限管理---------------");
                    // 请求的RUL地址和数据库是否匹配
                    boolean isMatch = false;
                    AntPathMatcher antPathMatcher = new AntPathMatcher();
                    //获取当前请求的URI地址
                    String requestURI = object.getRequest().getRequestURI();
                    System.out.println(requestURI);
                    List<MenuWithRoleVO> menuWithRoleVOS = sysUserService.getMenuWithRole();
                            System.out.println(menuWithRoleVOS);
                    for (MenuWithRoleVO menu : menuWithRoleVOS) {
//                        System.out.println(antPathMatcher.match(menu.getPath(), requestURI));
                        // antPathMatcher支持匹配，开头匹配和正则等多种方法
                        if (antPathMatcher.match(menu.getPath(), requestURI)) {
                            System.out.println("1");
                            isMatch = true;
                            List<RoleEntity> roleEntities = menu.getRoleEntities();
                            Collection<? extends GrantedAuthority> authorities = authentication.get().getAuthorities();
                            for (GrantedAuthority authority : authorities) {
                                System.out.println("2");
                                System.out.println(authority);
                                System.out.println(roleEntities);
                                for (RoleEntity roleEntity : roleEntities) {
                                    System.out.println("3");
                                    if (authority.getAuthority().equals(roleEntity.getRoleCode())) {
                                        System.out.println("-----------权限验证成功-------------");
                                        return new AuthorizationDecision(true);

                                    }
                                }
                            }
                        }
                    }
                    if (!isMatch) {
                        if (authentication.get() instanceof AnonymousAuthenticationToken) {
                            return new AuthorizationDecision(false);
                        } else {
                            System.out.println("---------已登录且无需验证---------");
                            return new AuthorizationDecision(true);
                        }
                    }
                    return new AuthorizationDecision(false);
                })
        );

        httpSecurity.authenticationProvider(authenticationProvider());
        // 禁用登陆页面
        httpSecurity.formLogin(AbstractHttpConfigurer::disable);
        // 禁用登出页面
        httpSecurity.logout(AbstractHttpConfigurer::disable);
        // 禁用session
        httpSecurity.sessionManagement(AbstractHttpConfigurer::disable);
        // 禁用httpbasic
        httpSecurity.httpBasic(AbstractHttpConfigurer::disable);
        // 禁用csrf
        httpSecurity.csrf(AbstractHttpConfigurer::disable);
        // 通过上下文获取AuthenticationManager
        AuthenticationManager authenticationManager = SpringContextUtils.getBean("authenticationManager");
        httpSecurity.addFilterBefore(new JwtAuthorizationFilter(authenticationManager), UsernamePasswordAuthenticationFilter.class);

        httpSecurity.exceptionHandling(exceptionHandling -> exceptionHandling
                .accessDeniedHandler(accessDeniedHandler));
//                .authenticationEntryPoint(authEntryPointHandler));

        return httpSecurity.build();
    }
}
